package com.liuqi.business.controller.front;

import com.alibaba.fastjson.JSONObject;
import com.github.pagehelper.PageInfo;
import com.google.common.base.Preconditions;
import com.liuqi.base.BaseFrontController;
import com.liuqi.business.constant.LockConstant;
import com.liuqi.business.dto.SelectDto;
import com.liuqi.business.enums.ProtocolEnum;
import com.liuqi.business.enums.SwitchEnum;
import com.liuqi.business.enums.WalletLogTypeEnum;
import com.liuqi.business.enums.YesNoEnum;
import com.liuqi.business.model.*;
import com.liuqi.business.service.*;
import com.liuqi.exception.NoLoginException;
import com.liuqi.redis.CodeCache;
import com.liuqi.redis.lock.RedissonLockUtil;
import com.liuqi.response.ReturnResponse;
import com.liuqi.utils.ShiroPasswdUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.apache.commons.lang3.StringUtils;
import org.redisson.api.RLock;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.ui.ModelMap;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import javax.validation.Valid;
import java.math.BigDecimal;
import java.util.Date;
import java.util.List;

/**
 * 财务中心
 */
@Api(description ="财务中心" )
@RequestMapping("/front/financial")
@RestController
public class FrontFinancialController extends BaseFrontController {
    @Autowired
    private UserWalletService userWalletService;
    @Autowired
    private RechargeService rechargeService;
    @Autowired
    private UserWalletAddressService userWalletAddressService;
    @Autowired
    private UserWalletLogService userWalletLogService;
    @Autowired
    private UserService userService;
    @Autowired
    private UserAuthService userAuthService;
    @Autowired
    private ExtractService extractService;
    @Autowired
    private CurrencyService currencyService;
    @Autowired
    private CurrencyRechargeService currencyRechargeService;
    @Autowired
    private CurrencyExtractService currencyExtractService;
    @Autowired
    private UserRechargeAddressService userRechargeAddressService;


    /**
     * 获取充币地址
     */
    @ApiOperation(value = "获取充值地址")
    @ApiImplicitParams({
            @ApiImplicitParam(dataType = "Long", name = "rechargeId", value = "充值id", required = true, paramType = "query")
    })
    @PostMapping("/rechargeInit")
    public ReturnResponse rechargeInit(HttpServletRequest request, @RequestParam("rechargeId") Long rechargeId) throws NoLoginException {
        Long userId = super.getUserId(request);
        CurrencyRechargeModelDto recharge = currencyRechargeService.getById(rechargeId);
        Preconditions.checkNotNull(recharge,"未查询到数据");
        //获取充值地址
        String address = this.getAddress(userId,recharge.getProtocol());
        JSONObject obj = new JSONObject();
        obj.put("switch", SwitchEnum.isOn(recharge.getRechargeSwitch()));//充值开关
        obj.put("min", recharge.getMinQuantity());//充值最小数量
        obj.put("memo", "");//标签
        obj.put("address", address);//充值地址
        if (ProtocolEnum.EOS.getCode().equals(recharge.getProtocol())
                ||ProtocolEnum.XRP.getCode().equals(recharge.getProtocol())) {
            obj.put("memo", address);//标签
            obj.put("address", recharge.getAddress());//充值地址
        }
        return ReturnResponse.backSuccess(obj);
    }

    private String getAddress(Long userId,Integer protocol){
        //协议2的地址
        String address = userRechargeAddressService.getRechargeAddress(userId, protocol);
        if (StringUtils.isEmpty(address)) {
            address = userRechargeAddressService.initRechargeAddressLock(userId,protocol);
        }
        return address;
    }

    /**
     * 查询充币记录
     *
     * @param request
     * @param pageNum
     * @param pageSize
     * @param currencyId
     * @return
     */
    @ApiOperation(value = "获取币种充值信息")
    @ApiImplicitParams({
            @ApiImplicitParam(dataType ="Integer",name="pageNum" ,value = "当前页",required = false,paramType = "query",defaultValue = "1"),
            @ApiImplicitParam(dataType = "Integer", name = "pageSize", value = "条数", required = false, paramType = "query", defaultValue = "20"),
            @ApiImplicitParam(dataType ="Long",name="currencyId" ,value = "币种",required = true,paramType = "query")
    })
    @PostMapping("/rechargeList")
    public ReturnResponse rechargeList(HttpServletRequest request, @RequestParam(defaultValue = "1", required = false) final Integer pageNum,
                                       @RequestParam(defaultValue = "20", required = false) final Integer pageSize, @RequestParam("currencyId") Long currencyId) throws NoLoginException {
        Long userId = super.getUserId(request);
        RechargeModelDto search=new RechargeModelDto();
        search.setUserId(userId);
        search.setCurrencyId(currencyId);
        //查询会员充币记录
        PageInfo<RechargeModelDto> pageInfo = rechargeService.queryFrontPageByDto(search, pageNum, pageSize);
        return ReturnResponse.backSuccess(pageInfo);
    }
    /**
     * 查询提币手续费地址
     *
     * @param request
     * @return
     */
    @ApiOperation(value = "查询提币手续费地址")
    @ApiImplicitParam(dataType ="Long",name="extractId" ,value = "提现id",required = true,paramType = "query")
    @PostMapping("/extractInit")
    public ReturnResponse extractInit(HttpServletRequest request, @RequestParam("extractId") Long extractId, ModelMap modelMap) throws NoLoginException {
        Long userId = super.getUserId(request);
        //查询提币手续费
        CurrencyExtractModelDto extract = currencyExtractService.getById(extractId);
        String poundage = extract.getRate().doubleValue() + "";
        // 查询提币地址
        UserWalletAddressModelDto search=new UserWalletAddressModelDto();
        search.setUserId(userId);
        search.setCurrencyId(extract.getCurrencyId());
        List<UserWalletAddressModelDto> list = userWalletAddressService.queryListByDto(search,true);
        BigDecimal using=BigDecimal.ZERO;

        UserWalletModel userWallet = userWalletService.getByUserAndCurrencyId(userId, extract.getCurrencyId());
        using=userWallet.getUsing();

        modelMap.put("switch", SwitchEnum.isOn(extract.getExtractSwitch()));//开关
        modelMap.put("rate", poundage);//手续费
        modelMap.put("percentage", YesNoEnum.YES.getCode().equals(extract.getType()));//是否百分比
        modelMap.put("min", extract.getMin());//最小数量
        modelMap.put("max", extract.getMax());//最大数量
        modelMap.put("day", extract.getMaxDay());//每天最大数量
        modelMap.put("daySwitch", SwitchEnum.isOn(extract.getMaxDaySwitch()));//每天最大值开关
        modelMap.put("using", using);//可用数量
        modelMap.put("addressList", list);//地址
        return ReturnResponse.backSuccess(modelMap);
    }
    /**
     * 提币申请
     *
     * @param extractCoinRecord
     * @param tradePassword
     * @param code
     * @param request
     * @return
     */
    @ApiOperation(value = "提币申请")
    @ApiImplicitParams({
            @ApiImplicitParam(dataType = "Long", name = "extractId", value = "提现id", required = true, paramType = "query"),
            @ApiImplicitParam(dataType = "BigDecimal", name = "quantity", value = "数量", required = true, paramType = "query"),
            @ApiImplicitParam(dataType = "String", name = "address", value = "地址", required = true, paramType = "query"),
            @ApiImplicitParam(dataType = "String", name = "memo", value = "eos标签", required = true, paramType = "query"),
            @ApiImplicitParam(dataType = "Long", name = "tradePassword", value = "交易密码", required = true, paramType = "query"),
            @ApiImplicitParam(dataType = "String", name = "code", value = "手机验证码", required = true, paramType = "query")
    })
    @PostMapping("/apply")
    @ResponseBody
    public ReturnResponse apply(@RequestParam("extractId") Long extractId,
                                @Valid ExtractModel extractCoinRecord,BindingResult bindingResult,
                                           @RequestParam("tradePassword") String tradePassword, @RequestParam("code") String code,
                                           HttpServletRequest request) throws NoLoginException {
        if (bindingResult.hasErrors()) {
            return ReturnResponse.backFail("参数异常:"+getErrorInfo(bindingResult));
        }
        if (extractCoinRecord.getQuantity().compareTo(BigDecimal.ZERO) <= 0) {
            return ReturnResponse.backFail("提币数量不能为负数");
        }
        CurrencyExtractModelDto extract = currencyExtractService.getById(extractId);
        extractCoinRecord.setCurrencyId(extract.getCurrencyId());
        extractCoinRecord.setProtocol(extract.getProtocol());
        //去除空格
        extractCoinRecord.setAddress(extractCoinRecord.getAddress().trim());
        extractCoinRecord.setMemo(extractCoinRecord.getMemo().trim());

        Long userId = super.getUserId(request);
        UserModelDto user = userService.getById(userId);
        if (!user.getTradePwd().equalsIgnoreCase(ShiroPasswdUtil.getUserPwd(tradePassword))) {
            return ReturnResponse.backFail("交易密码错误");
        }
        if (!SwitchEnum.isOn(extract.getExtractSwitch())) {
            return ReturnResponse.backFail("暂未开放");
        }
        if (extract.getMin().compareTo(BigDecimal.ZERO)>0 && extract.getMin().compareTo(extractCoinRecord.getQuantity()) > 0) {
            return ReturnResponse.backFail("小于提币最小值，最小值为："+extract.getMin());
        }
        if (extract.getMax().compareTo(BigDecimal.ZERO)>0 && extract.getMax().compareTo(extractCoinRecord.getQuantity()) < 0) {
            return ReturnResponse.backFail("超过提币最大值，最大值为："+ extract.getMax());
        }

        if (!userAuthService.auth(userId)) {//判断是否认证
            return ReturnResponse.backFail("用户未认证");
        }

        //验证短信密码
        CodeCache.verifyCode(user.getName(), code);

        String key = LockConstant.LOCK_EXTRACT_ORDER_USER + userId;
        RLock lock=null;
        try {
            lock = RedissonLockUtil.lock(key);
            extractCoinRecord.setUserId(userId);
            extractService.extractApply(extractCoinRecord,extract);
            return ReturnResponse.backSuccess();
        } catch (Exception e) {
            e.printStackTrace();
            return ReturnResponse.backFail(e.getMessage());
        } finally {
            RedissonLockUtil.unlock(lock);
        }
    }

    /**
     * 地址管理
     *
     * @param request
     * @param currencyId
     * @return
     */
    @ApiOperation(value = "获取设置的提现地址")
    @ApiImplicitParam(dataType ="Long",name="currencyId" ,value = "币种",required = true,paramType = "query")
    @PostMapping("/walletAddressList")
    public ReturnResponse walletAddressList(HttpServletRequest request,@RequestParam("currencyId") Long currencyId) throws NoLoginException {
        Long userId = super.getUserId(request);
        UserWalletAddressModelDto search=new UserWalletAddressModelDto();
        search.setUserId(userId);
        search.setCurrencyId(currencyId);
        List<UserWalletAddressModelDto> list = userWalletAddressService.queryListByDto(search,true);
        return ReturnResponse.backSuccess(list);
    }

    /**
     * 添加提币地址
     *
     * @param remark
     * @param currencyId
     * @param address
     * @param request
     * @return
     */
    @ApiOperation(value = "添加提现地址")
    @ApiImplicitParams({
            @ApiImplicitParam(dataType ="String",name="remark" ,value = "备注",required = true,paramType = "query"),
            @ApiImplicitParam(dataType ="Long",name="currencyId" ,value = "币种",required = true,paramType = "query"),
            @ApiImplicitParam(dataType ="String",name="address" ,value = "提币地址",required = true,paramType = "query"),
            @ApiImplicitParam(dataType ="String",name="memo" ,value = "标签",required = false,paramType = "query"),
            @ApiImplicitParam(dataType ="String",name="code" ,value = "手机验证码",required = true,paramType = "query")
    })
    @PostMapping("/addAddress")
    public ReturnResponse addAddress(@RequestParam("remark")String remark, @RequestParam("currencyId")Long currencyId,
                                     @RequestParam("address")String address,@RequestParam(value = "memo",required = false,defaultValue = "")String memo,
                                     @RequestParam("code")String code, HttpServletRequest request) throws NoLoginException {
        Long userId = super.getUserId(request);
        if (StringUtils.isAnyBlank(remark, address, code) || currencyId == null) {
            return ReturnResponse.backFail("参数错误");
        }
        address=address.trim();
        memo=memo.trim();

        UserModel userModel = userService.getById(userId);

        CodeCache.verifyCode(userModel.getName(), code);

        userWalletAddressService.addAddress(remark, currencyId, address,memo, userId);
        return ReturnResponse.backSuccess();
    }

    /**
     * 删除提币地址
     *
     * @param id
     * @return
     */
    @ApiOperation(value = "删除提现地址")
    @ApiImplicitParam(dataType ="Long",name="id" ,value = "id",required = true,paramType = "query")
    @PostMapping("/deleteAddress")
    public ReturnResponse deleteAddress(@RequestParam("id") Long id) {
        boolean flag = userWalletAddressService.delete(id);
        if (flag) {
            return ReturnResponse.backSuccess();
        } else {
            return ReturnResponse.backFail();
        }
    }


    /**
     * 查询提币记录
     *
     * @param request
     * @return
     */
    @ApiOperation(value = "查询提币记录")
    @ApiImplicitParams({
            @ApiImplicitParam(dataType = "Integer", name = "pageNum", value = "当前页", required = false, paramType = "query", defaultValue = "1"),
            @ApiImplicitParam(dataType = "Integer", name = "pageSize", value = "条数", required = false, paramType = "query", defaultValue = "20"),
            @ApiImplicitParam(dataType = "Long", name = "currencyId", value = "币种", required = true, paramType = "query")
    })
    @PostMapping("/extractList")
    public ReturnResponse extractList(HttpServletRequest request, @RequestParam("currencyId") Long currencyId, ModelMap modelMap,
                                      @RequestParam(defaultValue = "1", required = false) final Integer pageNum,
                                      @RequestParam(defaultValue = "20", required = false) final Integer pageSize) throws NoLoginException {
        Long userId = super.getUserId(request);
        ExtractModelDto search=new ExtractModelDto();
        search.setUserId(userId);
        search.setCurrencyId(currencyId);
        PageInfo<ExtractModelDto> pageInfo = extractService.queryFrontPageByDto(search, pageNum, pageSize);
        return ReturnResponse.backSuccess(pageInfo);
    }



    /**
     * 获取账单记录类型
     *
     * @param request
     * @return
     */
    @ApiOperation(value = "获取账单记录类型")
    @PostMapping("/getLogType")
    public ReturnResponse getLogType(HttpServletRequest request, ModelMap modelMap) throws NoLoginException {
        List<SelectDto> list= WalletLogTypeEnum.getList();
        return ReturnResponse.backSuccess(list);
    }
    /**
     * 获取账单
     */
    @ApiOperation(value = "获取账单")
    @ApiImplicitParams({
            @ApiImplicitParam(dataType ="Integer",name="pageNum" ,value = "当前页",required = false,paramType = "query",defaultValue = "1"),
            @ApiImplicitParam(dataType = "Integer", name = "pageSize", value = "条数", required = false, paramType = "query", defaultValue = "20"),
            @ApiImplicitParam(dataType ="Long",name="currencyId" ,value = "币种",required = false,paramType = "query"),
            @ApiImplicitParam(dataType ="Date",name="startDate" ,value = "开始时间",required = false,paramType = "query"),
            @ApiImplicitParam(dataType ="Date",name="endDate" ,value = "结束时间",required = false,paramType = "query"),
            @ApiImplicitParam(dataType ="Integer",name="type" ,value = "类型",required = false,paramType = "query"),
    })
    @PostMapping("/getLog")
    public ReturnResponse getLog(@RequestParam(value = "currencyId",required = false,defaultValue = "-2") Long currencyId,
                                 @RequestParam(value = "type",required = false) Integer type,
                                 @RequestParam(value = "startDate",required = false,defaultValue = "") Date startDate,
                                 @RequestParam(value = "endDate",required = false,defaultValue = "") Date endDate,
                                 @RequestParam(value = "pageNum",defaultValue = "1", required = false) final Integer pageNum,
                                 @RequestParam(value = "pageSize", defaultValue = "20", required = false) final Integer pageSize, HttpServletRequest request) throws NoLoginException {
        Long userId = super.getUserId(request);

        UserWalletLogModelDto search=new UserWalletLogModelDto();
        search.setUserId(userId);
        search.setCurrencyId(currencyId);
        search.setType(type);
        search.setStartCreateTime(startDate);
        search.setEndCreateTime(endDate);
        PageInfo<UserWalletLogModelDto> page = userWalletLogService.queryFrontPageByDto(search, pageNum, pageSize);
        return ReturnResponse.backSuccess(page);
    }
    @ApiOperation(value = "获取充提记录明细")
    @ApiImplicitParams({
            @ApiImplicitParam(dataType ="Integer",name="type" ,value = "类型1:充值 2提现",required = true,paramType = "query"),
            @ApiImplicitParam(dataType ="Long",name="id" ,value = "id",required = true,paramType = "query")
    })
    @PostMapping("/detailInfo")
    public ReturnResponse detailInfo(HttpServletRequest request, @RequestParam(value = "type",defaultValue = "1") Integer type, @RequestParam("id") Long id) throws NoLoginException {
        if (1 == type) {
            //查询会员充币记录
            RechargeModel recharge = rechargeService.getById(id);
            return ReturnResponse.backSuccess(recharge);
        } else {
            ExtractModel extract = extractService.getById(id);
            return ReturnResponse.backSuccess(extract);
        }
    }
}

